home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / qex / qexhfm / demo.cpp next >
Text File  |  1994-10-27  |  17KB  |  496 lines

  1. //----------------------------------------------------------------------------
  2. //                  Demo user interface software
  3. //
  4. //             "An Adaptive HF DSP Modem for 100 and 200 Baud"
  5. //                              QEX, Nov 1994.             
  6. //                                         
  7. //                    (c) Johan Forrer, KC7WW                     
  8. //                 26553 Priceview Drive                               
  9. //                         Monroe, OR 97456                     
  10. //----------------------------------------------------------------------------
  11. //                                       
  12. //     Compilation/link instructions for Borland C++ 4.0                                  
  13. //     >bcc -c -ml -O2 -Z -G demo.cpp
  14. //     >tlink /x c:\bc4\lib\c0l demo PSA1.obj PSA2.obj, emu mathl cl
  15. //                                       
  16. //----------------------------------------------------------------------------
  17. //              This is how the AD1848 is reprogrammed:
  18. //        Please the AD1848 data sheet for programming details.
  19. //----------------------------------------------------------------------------
  20. // Idx=0
  21. // Sta=0
  22. //  0 =0x00  select line with low gain
  23. //  1 =0x00  slecet line with low gain
  24. //  2 =0x80  mute left  aux#1
  25. //  3 =0x80  mute right aux#1
  26. //  4 =0x80  mute left  aux#2
  27. //  5 =0x80  mute right aux#2
  28. //  6 =0x07  left  DAC with some attenuation
  29. //  7 =0x07  right DAC with some attenuation
  30. //  8 =0x51  16 bit 2s compl, linear PCM, stereo, 
  31. //           xtal1=16.93MHz, 5512.5 kHz,
  32. //  9 =0x08  DMA capture/playback, Autocalibrate after mode change,
  33. //           disable capture/playback, dual DMA mode
  34. // 10 =0     N.A
  35. // 11 =0     N.A
  36. // 12 =0     N.A
  37. // 13 =0     digital mix muted
  38. // 14 =0     base count = 0
  39. // 15 =0     base count = 0
  40. //----------------------------------------------------------------------------
  41.  
  42. #include "psa.h"            // constants and includes 
  43.  
  44. #define DEFAULT_BGCOLOR     LIGHTBLUE    // our custom screen colors
  45. #define DEFAULT_CHCOLOR     LIGHTGRAY
  46. #define F1                  59        // simplify access to function keys
  47. #define F2                  60
  48. #define F3                  61
  49. #define F4                  62
  50. #define ALT_X               45
  51.  
  52. //----------------------------------------------------------------------------
  53. // Local function prototypes
  54. //----------------------------------------------------------------------------
  55. void prepare_DSP(char *, unsigned char *);
  56. void control_DSP(void);
  57. void shutdown_DSP(void);
  58. void run_user_interface();
  59. void tuning_bars();
  60. void pretty_print();
  61. void Adjust_Sound_input_level(int);
  62. void Adjust_Sound_output_level(int);
  63. void set_modem_baudrate(int);
  64. void set_AFSK_state(int);
  65.  
  66. #define MON "rte.ld"         // define name of bootstrap
  67. #define APP "modem.cde"        // define name of application
  68.  
  69. int peak_mark, peak_space;       // Global data
  70. int AF_source_in, Baudrate, Afsk;
  71.  
  72. //=====================START OF MAIN==========================================
  73. void main()
  74. {
  75. unsigned int boot_version;
  76. unsigned char initstate[18]={0,0,0x00,0x00,0x80,0x80,0x80,
  77.         0x80,0x07,0x07,0x51,0x08,0,0,0,0,0,0};
  78.  
  79. // ---------------------------------------------------------------------------
  80. // Check for presence and initialze DSP card
  81. // ---------------------------------------------------------------------------
  82.     if (!checkDSPcard(pssbase, wssbase)) {
  83.         printf("No PSA card - or WSS address is not available\n");
  84.         exit(0);
  85.         }
  86.  
  87. //----------------------------------------------------------------------------
  88. // Hard reset DSP
  89. //----------------------------------------------------------------------------
  90.     outpw(pssbase+PSS_CONTROL,PSS_RESET);    
  91.     outpw(pssbase+PSS_CONTROL,0);    
  92.  
  93. //--------------------------------------------------------------------------
  94. // Perform the DSP bootstrap next
  95. // and verify that it has completed successfully
  96. //--------------------------------------------------------------------------
  97.     boot_version=bootdsp(MON, NULL, (unsigned)16000);
  98.     checkdsptestprog();
  99.     printf("Monitor version %d.%d reported\n", 
  100.         boot_version>>8, boot_version&0x0F);
  101.  
  102. //----------------------------------------------------------------------------
  103. // Now we are ready to load the DSP application
  104. //----------------------------------------------------------------------------
  105.     prepare_DSP(APP, initstate);        // Initialize CODEC
  106.  
  107. //----------------------------------------------------------------------------
  108. // Prepare some initial sound levels. Note these may be a little
  109. // different for a Cardinal card.
  110. //    Source=0x00  - Line input for Orchid SW32
  111. //    Source=0x40  - Line input for Cardinal
  112. //    Source=0x80  - Mike input for Orchid
  113. //----------------------------------------------------------------------------
  114.     AF_source_in=0x80;        // I prefer to use Mike input
  115.     Adjust_Sound_input_level(7);    // Nice levels for Orchid
  116.     Adjust_Sound_output_level(35);
  117.     Baudrate=100;            // 100 baud
  118.     Afsk=0;                // AFSK is muted
  119.  
  120. //----------------------------------------------------------------------------
  121. // Finally we are ready to run the DSP application
  122. //----------------------------------------------------------------------------
  123.     control_DSP();                    // Run user interface
  124.     shutdown_DSP();                // Clean up after exit
  125. }
  126. //========================END OF MAIN========================================
  127.  
  128.  
  129. //---------------------------------------------------------------------------
  130. //                    Some local functions
  131. //---------------------------------------------------------------------------
  132.  
  133. //-------------This is where the user interface goes-------------------------
  134. void run_user_interface()
  135. {
  136. char ch;
  137.     pretty_print();            // Print program's static text
  138.     set_modem_baudrate(Baudrate);
  139.     set_AFSK_state(Afsk);
  140.  
  141.     for(;;) {
  142.         delay(40);        // slow down screen updates
  143.         tuning_bars();        // update tuning displays
  144.  
  145. //----------------------------------------------------------------------------
  146. // Service the user's keyboard
  147. //----------------------------------------------------------------------------
  148.         if(kbhit()) {
  149.             ch=getch();
  150.                  if(ch==0) {                    // 0 code
  151.                         ch=getch();
  152.                         switch(ch) {
  153.                                case F1:        // F1
  154.                                       break;
  155.  
  156.                                case F2:        // F2
  157.                                       break;
  158.  
  159.                                case F3:        // F3
  160.                         if(Baudrate==100) 
  161.                             Baudrate=200;
  162.                         else    Baudrate=100;
  163.                         set_modem_baudrate(Baudrate);
  164.                                       break;
  165.  
  166.                     case F4:    // F4
  167.                         if(Afsk==0) Afsk=1;
  168.                         else if(Afsk==1) Afsk=2;
  169.                         else if(Afsk==2) Afsk=0;
  170.                         set_AFSK_state(Afsk);
  171.                         break;
  172.                     case ALT_X:     // Breakout
  173.                         ch=0x1B; // force ESC
  174.                         break;        
  175.                     }
  176.                 }
  177.             if(ch==0x1B) break;
  178.             }
  179.         }
  180.         
  181.     while(kbhit()) getch();        // flush out breakout charater
  182.  
  183. //---------------------------------------------------------------------------
  184. // Restore display to the state before we ran
  185. //---------------------------------------------------------------------------
  186.        _setcursortype( _NORMALCURSOR );
  187.     normvideo();
  188.         window(1,1,80,25); clrscr();
  189. }
  190.  
  191. //----------------------------------------------------------------------------
  192. // Routine to load & run DSP application
  193. //----------------------------------------------------------------------------
  194. void prepare_DSP(char *app_name, unsigned char ad1848_state[])
  195. {
  196.     load_DSP_mem(app_name);       // load the DSP application code
  197.  
  198.     set1848state(ad1848_state); // reprogram CODEC
  199.  
  200.     outp(wssbase+WSS_CODECINDEXADDR,0x0009); // Capture/Playback on
  201.     outp(wssbase+WSS_CODECINDEXDATA,0x0003); 
  202.  
  203.     putdspword(0x00B4);        // send "start application" code to DSP 
  204. }
  205.  
  206. //----------------------------------------------------------------------------
  207. // Routine to terminate DSP application
  208. //----------------------------------------------------------------------------
  209. void shutdown_DSP()
  210. {
  211.     putdspword(0x00B5);    // send "stop application" code to DSP
  212.  
  213.     outp(wssbase+WSS_CODECINDEXDATA,0x0009); // Playback/capture off 
  214.     outp(wssbase+WSS_CODECINDEXDATA, 0);
  215.  
  216.     outp(wssbase+WSS_CODECINDEXADDR,0x0006);  // mute DAC
  217.     outp(wssbase+WSS_CODECINDEXDATA, 0xDF);
  218.     outp(wssbase+WSS_CODECINDEXADDR,0x0007);
  219.     outp(wssbase+WSS_CODECINDEXDATA, 0xDF);
  220.  
  221. }
  222.  
  223. //----------------------------------------------------------------------------
  224. // Prepare and run the user's interface program
  225. //
  226. //      This is a four parter:
  227. //
  228. //     1). Preparing the PC's interrupt system.
  229. //     2). Starting the DSP timer to allow low-level communication 
  230. //          between the PC and DSP.
  231. //     3). Initiate and run the user's interface code until completion.
  232. //     4). Terminating the DSP timer and close down low-level
  233. //          communication between the PC and DSP.
  234. //----------------------------------------------------------------------------
  235.  
  236. void control_DSP()
  237. //----------------------------------------------------------------------------
  238. {
  239. // Define ISR prototypes
  240. void interrupt (*oldfunc)(...);        // for storage of old vector
  241. void interrupt DSP_int_serv(...);      // Prototype for new interrupt serv.
  242. unsigned char old_IMR;            // Save old PIC IMR
  243.  
  244. //---------------------------------------------------------------------------
  245. // Preparing the PC's Interrupt system
  246. //---------------------------------------------------------------------------
  247.     oldfunc=getvect(INT);        // Hook IRQ7 on the PC side
  248.     setvect(INT,DSP_int_serv);
  249.  
  250. // Set INT7 on DSP side as well
  251.     outpw(pssbase+PSS_CONFIG,IRQ7);
  252.     old_IMR=inp(0x21);        // get IMR
  253.     outp(0x21,old_IMR&0x7F);    // Arm PC's IRQ7 in IMR
  254.  
  255. //---------------------------------------------------------------------------
  256. // Starting the DSP timer to allow low-level communication 
  257. // between the PC and DSP.
  258. //---------------------------------------------------------------------------
  259.     putdspword(0x00B0);        // send "start timer" code to DSP
  260.  
  261. //---------------------------------------------------------------------------
  262. // Initiate and run the user's interface code until completion.
  263. //---------------------------------------------------------------------------
  264.     run_user_interface();
  265.  
  266. //---------------------------------------------------------------------------
  267. // Terminating the DSP timer and close down low-level
  268. // communication between the PC and DSP.
  269. //---------------------------------------------------------------------------
  270.     putdspword(0x00B1);             // send "stop timer" code to DSP
  271.  
  272.     outpw(pssbase+PSS_IRQ_ACK, 0);    // Clear any pending PSA interrupts
  273.     outpw(pssbase+PSS_CONFIG,0x0000);  // Remove PSA from IRQ7
  274.  
  275.     outp(0x21,old_IMR);        // Restore IMR
  276.  
  277.     setvect(INT, oldfunc);        // Restore INT
  278. }    
  279.  
  280. //----------------------------------------------------------------------------
  281. // The new IRQ7 interrupt handler
  282. //----------------------------------------------------------------------------
  283. void interrupt DSP_int_serv(...)
  284. {
  285. #define DECAY 50            // Decay factor for tuning display
  286. int mark, space, AD_data;
  287.  
  288.     outpw(pssbase+PSS_IRQ_ACK, 0);    // Clear the interrupt
  289.     outp(0x20,0x20);         // write EOI to PIC 
  290.                     // else bad things happen!
  291.  
  292. //------------------Process recovered data from DSP---------------------------
  293. // Get signal from DSP demodulator. Separate into mark & space peak levels.                 
  294. //----------------------------------------------------------------------------
  295.     AD_data=inpw(pssbase+PSS_DATA);
  296.     if(AD_data<0) {
  297.         space=(-AD_data);
  298.         if(space>peak_space) peak_space=space;
  299.         else                 peak_space=peak_space-DECAY;
  300.         }
  301.     else    {
  302.               mark =  AD_data;
  303.         if(mark>peak_mark)   peak_mark=mark;
  304.         else             peak_mark=peak_mark-DECAY;
  305.         }
  306. }
  307.  
  308. //--------------------------------------------------------------------------
  309. // Display tuning bars
  310. //
  311. // Channel data >=10 displays in RED
  312. // Channel data =8 or 9 displays in YELLOW
  313. //
  314. // The raw channel data from the DSP is a single signed 16-bit value. It
  315. // is first interpreted, i.e., positive values are MARK, negative
  316. // values are SPACE. A simple peak-detector algorithm improves visualization.
  317. // The peak values for MARK and SPACE are used in the display routine
  318. // where they are scaled and clipped, and averaged to fit into the tuning 
  319. // dispay template. 
  320. //--------------------------------------------------------------------------
  321. void tuning_bars()
  322. {
  323. #define TUN 32                // Center tuning display
  324.  
  325. int stat, i, j, mark_tuning, space_tuning;
  326. static int mark, space;
  327. static char upper_row[]="m┌┬┬┬┬┬┬┬┬┬┬┬┐m  ";   // Tuning display templates
  328. static char lower_row[]="s└┴┴┴┴┴┴┴┴┴┴┴┘s  ";
  329.  
  330.     mark_tuning=(peak_mark>>8);    // scale to a usable level
  331.     space_tuning=(peak_space>>8);
  332.  
  333.     mark=(mark+mark_tuning)>>1;    // Average mark with prev.
  334.     space=(space+space_tuning)>>1; // Average space with prev.
  335.  
  336.     if(mark>=10)  mark=10;
  337.     if(space>=10) space=10;
  338.  
  339.     gotoxy(TUN,3);
  340.     for(j=0; j<15; j++) cprintf("%c", upper_row[j]);
  341.     gotoxy(TUN,4);
  342.     for(j=0; j<15; j++) cprintf("%c", lower_row[j]);
  343.  
  344.  
  345.     if(mark>=10) {
  346.         textattr(0x7F&(RED+(DEFAULT_BGCOLOR<<4)));
  347.         gotoxy(TUN+12-mark,3); 
  348.         cprintf("▄");
  349.         }
  350.     else mark++;
  351.     for(i=mark-1; i>=0 ;i--)
  352.         if((mark>7)&&(i>=7)) {
  353.             gotoxy(TUN+12-i,3); 
  354.             textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  355.             cprintf("▄");
  356.             }
  357.         else 
  358.             if((mark>4)&&(i>=4)) {
  359.                 gotoxy(TUN+12-i,3); 
  360.                 textattr(0x7F&(LIGHTBLUE+(DEFAULT_BGCOLOR<<4)));
  361.                 cprintf("▄");
  362.                 }
  363.             else {
  364.                 gotoxy(TUN+12-i,3); 
  365.                 textattr(0x7F&(LIGHTGRAY+(DEFAULT_BGCOLOR<<4)));
  366.                 cprintf("▄");
  367.                 }
  368.  
  369.     if(space>=10) {
  370.         textattr(0x7F&(RED+(DEFAULT_BGCOLOR<<4)));
  371.         gotoxy(TUN+12-space,4); 
  372.         cprintf("▀");
  373.         }
  374.     else space++;
  375.     for(i=space-1; i>=0 ;i--)
  376.         if((space>7)&&(i>=7)) {
  377.             gotoxy(TUN+12-i,4); 
  378.             textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  379.             cprintf("▀");
  380.             }
  381.         else
  382.             if((space>4)&&(i>=4)) {
  383.                 gotoxy(TUN+12-i,4); 
  384.                 textattr(0x7F&(LIGHTBLUE+(DEFAULT_BGCOLOR<<4)));
  385.                 cprintf("▀");
  386.                 }
  387.             else {
  388.                 gotoxy(TUN+12-i,4); 
  389.                 textattr(0x7F&(LIGHTGRAY+(DEFAULT_BGCOLOR<<4)));
  390.                 cprintf("▀");
  391.                 }
  392.  
  393.     textcolor(DEFAULT_CHCOLOR);
  394.     textbackground(DEFAULT_BGCOLOR);
  395. }
  396.  
  397. //----------------------------------------------------------------------------
  398. // Static screen text
  399. //----------------------------------------------------------------------------
  400. void pretty_print()
  401. {
  402.     textbackground(DEFAULT_BGCOLOR); // Default screen colors
  403.     textcolor(DEFAULT_CHCOLOR);
  404.     _setcursortype(_NOCURSOR);
  405.     clrscr();
  406.     gotoxy(1,2); 
  407.     cprintf("══════════════════════║ DEMO MODEM CONTROL (c) KC7WW");
  408.     cprintf(" ║═════════════════════════");
  409.  
  410.     gotoxy(1,25); 
  411.     textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  412.     cprintf("F1");
  413.     textbackground(DEFAULT_BGCOLOR);
  414.     textcolor(DEFAULT_CHCOLOR);
  415.     cprintf("=Input level "); 
  416.     textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  417.     cprintf("F2");
  418.     textbackground(DEFAULT_BGCOLOR);
  419.     textcolor(DEFAULT_CHCOLOR);
  420.     cprintf("=Speaker level "); 
  421.     textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  422.     cprintf("F3");
  423.     textbackground(DEFAULT_BGCOLOR);
  424.     textcolor(DEFAULT_CHCOLOR);
  425.     cprintf("=Modem "); 
  426.     textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  427.     cprintf("F4");
  428.     textbackground(DEFAULT_BGCOLOR);
  429.     textcolor(DEFAULT_CHCOLOR);
  430.     cprintf("=AFSK ");
  431.     textattr(0x7F&(YELLOW+(DEFAULT_BGCOLOR<<4)));
  432.     cprintf("ALT-X or ESC");
  433.     textbackground(DEFAULT_BGCOLOR);
  434.     textcolor(DEFAULT_CHCOLOR);
  435.     cprintf("=Quit");
  436.     textbackground(DEFAULT_BGCOLOR);
  437.     textcolor(DEFAULT_CHCOLOR);
  438. }
  439.  
  440. //---------------------------------------------------------------------------
  441. // This adjusts the level of the line in
  442. //---------------------------------------------------------------------------
  443. void Adjust_Sound_input_level(int level)
  444. {
  445.     asm {cli}
  446.     putdspword(0x00BC);
  447.     putdspword((AF_source_in+level)<<8);
  448.     asm {sti}
  449. }
  450.  
  451. //---------------------------------------------------------------------------
  452. // This adjusts the level of the speaker level
  453. //---------------------------------------------------------------------------
  454. void Adjust_Sound_output_level(int level)
  455. {
  456.     asm {cli}
  457.     putdspword(0x00BB);
  458.     putdspword((0x007F-level)<<8);
  459.     asm {sti}
  460. }
  461.  
  462. //---------------------------------------------------------------------------
  463. // This changes the modem's baudrate
  464. //---------------------------------------------------------------------------
  465. void set_modem_baudrate(int rate)
  466. {
  467.     asm {cli}
  468.     if(rate==100) putdspword(0x00BE);
  469.     else          putdspword(0x01BE);
  470.     asm {sti}
  471.  
  472. // Update display to reflect new baudrate
  473.     gotoxy(60,3); cprintf("%d  - BAUD",rate);
  474. }
  475.  
  476. //---------------------------------------------------------------------------
  477. // This changes the AFSK generator's state
  478. //---------------------------------------------------------------------------
  479. void set_AFSK_state(int state)
  480. {
  481.     asm {cli}
  482.     putdspword(0x00BD+(state<<8));
  483.     asm {sti}
  484.  
  485. // Update display to reflect the new state
  486.     gotoxy(60,4); 
  487.     switch (state) {
  488.         case 0: cprintf("AFSK - MUTED");
  489.             break;
  490.         case 1: cprintf("AFSK - MARK ");
  491.             break;
  492.         case 2: cprintf("AFSK - SPACE");
  493.             break;
  494.         }
  495. }
  496.